﻿/*
* Copyright (C) 2020 ~ 2024 chaigec All Rights Reserved.
*
* Author:     chaigec <chaigec@163.com>
* Maintainer: chaigec <chaigec@163.com>

 * Use of this source code is governed by MIT license that can be found in the
 * LICENSE file in the root of the source tree. All contributing project authors
 * may be found in the AUTHORS file in the root of the source tree.
*/

#include "MkThread.h"
#include "MkLog.h"
#include "MkUtil.h"
#ifdef _WIN32
#include <process.h>
#else
#include <unistd.h>
#endif
CMkThread::CMkThread()
{
    m_ThreadHandle = 0;
}

Uint32 CMkThread::Start(ThreadFun Func)
{
    m_Fun = Func;
#ifdef _WIN32
    Uint32 threadId = 0;
    m_ThreadHandle = (HANDLE)_beginthreadex(NULL, 0, Thread, this, NULL, &threadId);
#else
    pthread_create(&m_ThreadHandle, nullptr, threadrun, this);
    //MkDebugLog("start thread:%d\n", m_ThreadHandle);
#endif
    if (!m_ThreadHandle) {
        return CreateThreadFailed;
    }
    return NoneError;
}

void CMkThread::Stop()
{
    if (!m_ThreadHandle) {
        return;
    }
#ifdef _WIN32
    DWORD nRet = WaitForSingleObject(m_ThreadHandle, 3000);
    if (nRet == WAIT_TIMEOUT) {
        TerminateThread(m_ThreadHandle, 2);
    }
    CloseHandle(m_ThreadHandle);
#else
    void *status;
    pthread_join(m_ThreadHandle, &status);
    //MkDebugLog("wait thread :%d exit value(%p)\n", m_ThreadHandle, status);
#endif
    m_ThreadHandle = 0;
}

#ifdef _WIN32
unsigned int __stdcall CMkThread::Thread(void *lParam)
{
#else
void *CMkThread::threadrun(void *lParam)
{
    //pthread_detach(pthread_self());
    //pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
#endif
    CMkThread *pThread = static_cast<CMkThread *>(lParam);
    if (pThread && pThread->m_Fun) {
        pThread->m_ThreadId = CMkUtil::GetLocalThreadId();
        pThread->m_Fun();
    }
#ifdef _WIN32
    return 0;
#else
    return nullptr;
#endif
}

void CMkThread::ThreadSleep(Uint32 dwMilliseconds)
{
#ifdef _WIN32
    Sleep(dwMilliseconds);
#else
    usleep(1000 * dwMilliseconds);
#endif
}

CMkThread::~CMkThread()
{
    Stop();
}
